#pragma once

#include "FloorsContainer.h"
#include "Elevator.h"

#define INIFINITY -1 // Elevator will stops after transporting all pasenger. No further generation

class CFloorsManager;
struct IDrawable
{
	virtual void Draw(IFloorsContainer* floorsContainer) = 0;
};

class CFloorsManager : public IFloorsContainer
{
public:
	CFloorsManager(size_t elevatorCapacity, size_t passengersIntensity = 0, int stepsToDo = INIFINITY, IDrawable* drawer = NULL);
	~CFloorsManager(void);

	void SetUpdateListener(IUpdateListener* updateListener);
	void GenerateFloors(size_t num);
	
	virtual const FloorsCollection& GetFloors() const { return m_floors; };
	virtual IElevator* GetElevator() { return &m_elevator; };
	virtual size_t GetSteps() const { return m_steps; };
	virtual size_t GetIntensity() const { return m_passengersIntensity; };
	virtual size_t GetTotallyTransported() const { return m_transported; };
	virtual bool ShouldStop() const{ return m_shouldStop; };
	virtual size_t GetAverageElevatorLoad() const;

	bool ImportPassengersToFloor(size_t floor, const std::vector<size_t>& passengersTargets);
	void Start();
	void Redraw();
private:
	FloorsCollection m_floors;
	CElevator m_elevator;
	IDrawable* m_drawer;
	size_t m_passengersIntensity;
	size_t m_steps;
	size_t m_transported;
	int m_stepsToDo;
	bool m_shouldStop;
	std::vector<size_t> m_incomingPassengersCount;

	void GeneratePassengers(size_t maxPassengerPerFloor);

	class CFloorsManagerListener
	{
	protected:
		CFloorsManager& m_manager;
		CFloorsManagerListener(CFloorsManager& fm) : m_manager(fm){}
	};

	struct CStepsChangeListener : public IElevatorActionListener, CFloorsManagerListener
	{
		CStepsChangeListener(CFloorsManager& fm) : CFloorsManagerListener(fm){}
		virtual void OnElevatorAction();
	};

	struct CTransportedListener : public IPassengertransportedListener, CFloorsManagerListener
	{
		CTransportedListener(CFloorsManager& fm) : CFloorsManagerListener(fm){}
		virtual void OnPassengerTransported();
	};

	struct CLoadPassengersListener : public ILoadPassengersListener, CFloorsManagerListener
	{
		CLoadPassengersListener(CFloorsManager& fm) : CFloorsManagerListener(fm){}
		virtual void LoadPassengersAtArival(PassengerCollection& incomingPassengers);
	};
};

